#include "LogDirCtrl.h"

LogDirCtrl::LogDirCtrl():
pszPokyLogName(NULL)
{
     szFilePath = (char *)malloc(100);
}

LogDirCtrl::~LogDirCtrl()
{
    free(szFilePath);
}

bool LogDirCtrl::LogDirCtrl_Init(char** _pszFileName)
{
    XAG_RETURN(*_pszFileName == NULL,false,"_pszFileName is not null!\n");
    
    int s32HeadFileIndex = 0;
    int s32TailFileIndex = 0;
    
   
    
    pszPokyLogName = (char*)xag_malloc(POKY_LOG_NAME_SIZE);
    memset(pszPokyLogName,0,POKY_LOG_NAME_SIZE-1);
    *_pszFileName = pszPokyLogName;
    
    scanfLogFile();
    
    getFileIndex(&s32HeadFileIndex, &s32TailFileIndex);

    addLogFile(s32TailFileIndex + 1);
    
    m_running = 1;
    char *pCodePosition;
    XAG_CODE_POSITION_GET(pCodePosition);
    XAG_ThreadWrapper::XAG_ThreadWrapper_Creat(&m_pid,Workcallback, this,pCodePosition);
   
    printf("LogDirCtrl_Init success\n");
    return true;
}

void LogDirCtrl::LogDirCtrl_Relese()
{
    m_running = 0;
    XAG_ThreadWrapper::XAG_ThreadWrapper_Join(m_pid);
   
//    vector<int>::iterator itr = m_filelist.begin();
//    for (itr; itr != m_filelist.end(); ++itr)
//    {  
//        m_filelist.erase(itr);  
//    }
    xag_free(pszPokyLogName);
    pszPokyLogName = NULL;
    printf("LogDirCtrl_Relese success\n");
}

/**线程工作函数*/
bool LogDirCtrl::Workcallback(void* param)
{
    LogDirCtrl* pThis = (LogDirCtrl*) param;
    pThis->Work();
    return true;
}

void LogDirCtrl::Work()
{
    int s32Ret = 0;
    long s32Size = 0;
    int s32Ri = 0;
    XAG_TIMEV tBegin;
    XAG_TIMEV tNow;
    XAG_TIMEV tSub;
    
    tBegin = XAG_TIME_COMMON_GetMonotonic();

    //###################################################
    s32Ret = getDirFileCount(MONITORING_LOG_SYSTEM); 
    if (s32Ret > MAX_LOG_FILE_COUNTS)
    {   
        printf("camera log more than %d,it's[%d],and delete the beyond\n",MAX_LOG_FILE_COUNTS, s32Ret);

        scanfLogFilebyTime(); //找.log文件
        _sortLogFileList(m_filetimelist); //排序
        for (s32Ri = 0; s32Ri < s32Ret - MAX_LOG_FILE_COUNTS; s32Ri++)           
            delLogFileByTime(m_filetimelist[s32Ri].time); 
        
    }
    //###################################################
     AutoDetectImageDir();
    //########################################################
    AutoDetectFlyMapOutDir();
    //########################################################
    while (m_running)
    { 
          
        tNow = XAG_TIME_COMMON_GetMonotonic();
        tSub = XAG_TIME_COMMON_TimevSub(tNow,tBegin);
        if(tSub.tv_sec > 4)
        {    
            
            //目录大小超过最大值，删除旧的log文件
            deleteOldFile();

            //检测当前重定向写入的日志文件，如果超过最大值，则写入到下一个文件
            detectcurfile();
            tBegin = XAG_TIME_COMMON_GetMonotonic();
        }
        usleep(200000);
    }
    
}

void LogDirCtrl::deleteOldFile()
{
    int s32HeadFileIndex = 0;
    int s32TailFileIndex = 0;
    
    //目录大小超过最大值，删除旧的log文件 
    unsigned long dirsize = getDirSize(szFilePath);

    unsigned long tmp = LOG_DIR_MAX_SIZE;
    if (dirsize > tmp)
    {
        getFileIndex(&s32HeadFileIndex, &s32TailFileIndex);
        delLogFile(s32HeadFileIndex);
    }
}

void LogDirCtrl::scanfLogFile()
{
    DIR *dp;
    struct dirent *dirp;

    bzero(szFilePath,sizeof(szFilePath));
    sprintf(szFilePath,"%s",MONITORING_LOG_SYSTEM);
    
    if(access(szFilePath,F_OK) != 0)
    {
        //mkdir(szFilePath,0777);
        char cmd[100];
        sprintf(cmd,"mkdir -p %s",szFilePath);
        system(cmd);
    }
    
    if ((dp = opendir(szFilePath)) == NULL)
    {
        XAG_LOG_E("can't open %s", szFilePath);
        return;
    }

    while ((dirp = readdir(dp)) != NULL)
    {
        if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
            continue;
        string strtmp = dirp->d_name;
        if (strtmp.find(LOG_FILE_PRE) == 0)
        {
            char right[16] = {0};
            int len1 = strlen(dirp->d_name);
            int len2 = strlen(LOG_FILE_PRE);
            if (len1 > len2)
            {
                memcpy(right, dirp->d_name + len2, len1 - len2);
                int tmpint = atoi(right);
                m_filelist.push_back(tmpint);
            }
        }
    }

    closedir(dp);
}

void LogDirCtrl::scanfLogFilebyTime()
{

    int s32LogFilePathLen; 
    int s32LogFileLastLen;
        
    char szLogFileTimeName[LOG_TIME_LEN + 1] = {0};
    char szCmd[100] = {0x00};
    
    char* pStrtmp = NULL;  
    
    LOGFILE_INFO stLogFileInfo;
    DIR *dp;
    struct dirent *dirp;

    bzero(szFilePath, sizeof (szFilePath));
    memcpy(szFilePath, MONITORING_LOG_SYSTEM, sizeof (szFilePath));
    if (access(szFilePath, F_OK) != 0)
    {
        mkdir(szFilePath, 0777);
    }
 
    if ((dp = opendir(szFilePath)) == NULL)
    {
        XAG_LOG_E("can't open %s", szFilePath);
        return;
    }

    s32LogFileLastLen = strlen(LOG_FILE_LAST);
    
    while ((dirp = readdir(dp)) != NULL)
    {
        if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
            continue;
        
        pStrtmp= dirp->d_name;

        s32LogFilePathLen = strlen(dirp->d_name);
        
        //continue;
        if (strstr(pStrtmp, LOG_FILE_LAST) && s32LogFilePathLen > LOG_TIME_LEN + 3)
        {
            if (strstr(pStrtmp, LOG_FILE_MONITORING) == NULL)
            {
                //printf("#####scanfLogFilebyTime name=%s,len1=%d######\n",dirp->d_name,len1);
                memset(szLogFileTimeName,0,sizeof(szLogFileTimeName));
                memcpy(szLogFileTimeName, pStrtmp + (s32LogFilePathLen - s32LogFileLastLen - LOG_TIME_LEN), LOG_TIME_LEN);
                //printf("#####scanfLogFilebyTime left=%s######\n",left);
                if (_isTimeStr(szLogFileTimeName))//是合法的时间命名
                {
                    _del_char(szLogFileTimeName, '_');
                    //printf("#####scanfLogFilebyTime left1111=%s######\n",left);
                    long tmpint = atoll(szLogFileTimeName);
                    memset(&stLogFileInfo,0,sizeof(stLogFileInfo));
                    stLogFileInfo.time = tmpint;
                    memcpy(stLogFileInfo.FileName, pStrtmp, strlen(pStrtmp));
                    m_filetimelist.push_back(stLogFileInfo);
                }
                else
                {
                    bzero(szCmd,sizeof(szCmd));
                    sprintf(szCmd, "%s/%s", MONITORING_LOG_SYSTEM, pStrtmp);
                    remove(szCmd);

                }
            }
        }
        else
        {
            if (strstr(pStrtmp, LOG_FILE_MONITORING) == NULL)
            {
                bzero(szCmd,sizeof(szCmd));
                sprintf(szCmd, "%s/%s", MONITORING_LOG_SYSTEM, pStrtmp);
                remove(szCmd);
            }
        }
    }

    closedir(dp);
}

void LogDirCtrl::getFileIndex(int *ps32Head, int *ps32Tail)
{
    int s32Head = 0;
    int s32Tail = 0;
    int i;
    
    if (m_filelist.size() > 0)
    {
        s32Head = m_filelist[0];
        s32Tail = m_filelist[0];

        for (i = 0; i < m_filelist.size(); ++i)
        {
            if (s32Head > m_filelist[i])
                s32Head = m_filelist[i];
            
            if (s32Tail < m_filelist[i])
                s32Tail = m_filelist[i];
        }
    }
    
    *ps32Head = s32Head;
    *ps32Tail = s32Tail;
}

void LogDirCtrl::delLogFile(int index)
{
    char curfile[100] = {0x00};
    
    bzero(curfile,sizeof(curfile));
    sprintf(curfile, "%s%s%d", szFilePath, LOG_FILE_PRE, index);
    remove(curfile);
    
    vector<int>::iterator itr = m_filelist.begin();
    for (itr; itr != m_filelist.end(); ++itr)
    {
        if (*itr == index)
        {
            m_filelist.erase(itr);
            break;
        }
    }
}

void LogDirCtrl::delLogFileByTime(long time)//删除对应time的日志文件
{
    char cmd[100] = {0x00};
    char curfile[100] = {0x00};
    char* FileName = NULL;
    bzero(curfile, sizeof (curfile));
    //printf("delLogFileByTime time=%lld\n",time);
    FileName = GetLogNameByTime(time);
    if (FileName)
    {
        sprintf(curfile, "%s/%s", MONITORING_LOG_SYSTEM, FileName);
        printf("del Log File %s\n",curfile);
    }
    sprintf(cmd, "rm -r %s", curfile);
    system(cmd);
//    remove(curfile);

    vector<LOGFILE_INFO>::iterator itrTime = m_filetimelist.begin();
    for (itrTime; itrTime != m_filetimelist.end(); ++itrTime)
    {
        if (itrTime->time == time)
        {
            m_filetimelist.erase(itrTime);
            break;
        }
    }
}

void LogDirCtrl::delDirFileByTime(long times,int type)//删除对应time的flymap文件夹
{
    // printf("delLogFileByTime time=%lld\n",time);
    char cmd[100] = {0x00};
    char curdir[100] = {0x00};
    char* DirName = NULL;
    bzero(curdir, sizeof (curdir));
   
   if(type==IMAGEDIR)
   {
    DirName = GetImageDirNameByTime(times);
    if (DirName)
    {
        sprintf(curdir, "%s/%s", IMAGE_STORE_DIR, DirName);
        printf("del img File %s\n",curdir);
    }
    sprintf(cmd, "rm -r %s", curdir);
    system(cmd);
//    remove(curfile);

    vector<ImageDir_INFO>::iterator itrTime = m_imagedirtimelist.begin();
    for (itrTime; itrTime != m_imagedirtimelist.end(); ++itrTime)
    {
        if (itrTime->time == times)
        {
            m_imagedirtimelist.erase(itrTime);
            break;
        }
    }
   }
 else if(type==FLYMAPOUTDIR)
 {
	   DirName = GetFlymapOutDirNameByTime(times);
	   if (DirName)
	   {
		   sprintf(curdir, "%s/%s", FLYMAP_OUT_DIR, DirName);
		   printf("del flymapout File %s\n",curdir);
	   }
	   sprintf(cmd, "rm -r %s", curdir);
	   system(cmd);
   //	 remove(curfile);
   
	   vector<FlyMapOutDir_INFO>::iterator itrTime = m_outdirtimelist.begin();
	   for (itrTime; itrTime != m_outdirtimelist.end(); ++itrTime)
	   {
		   if (itrTime->time == times)
		   {
			   m_outdirtimelist.erase(itrTime);
			   break;
		   }
	   }
  }
   
}


void LogDirCtrl::detectcurfile()
{
   
    char curfile[100] = {0};
    sprintf(curfile, "%s%s%d", szFilePath, LOG_FILE_PRE, m_curfile);

    unsigned long filesize = 0;
    FILE *fp;
    fp = fopen(curfile, "r");
    if (fp == 0)
        return;
    fseek(fp, 0L, SEEK_END);
    filesize = ftell(fp);
    fclose(fp);
    if (filesize > LOG_ONE_FILE_MAX_SIZE)
    {
        addLogFile(m_curfile + 1);
    }
}


void LogDirCtrl::addLogFile(int index)
{
    char curfile[100] = {0x00};
    bzero(curfile,sizeof(curfile));
    sprintf(curfile, "%s%s%d", szFilePath, LOG_FILE_PRE, index);
    
    memset(pszPokyLogName,0,POKY_LOG_NAME_SIZE-1);
    memcpy(pszPokyLogName,curfile,strlen(curfile));
   
    m_curfile = index;
    m_filelist.push_back(m_curfile);
}

unsigned long LogDirCtrl::getDirSize(char *dir)
{
       long totalSize = 0;
       DIR *dp;
       struct dirent *entry;
       struct stat statbuf;

	if ((dp = opendir(dir)) == NULL)
	{
		fprintf(stderr, "Cannot open dir: %s\n", dir);
		return -1; //可能是个文件，或者目录不存在
	}
	
	//先加上自身目录的大小
	lstat(dir, &statbuf);
	totalSize+=statbuf.st_size;

	while ((entry = readdir(dp)) != NULL)
	{
		char subdir[256];
		sprintf(subdir, "%s/%s", dir, entry->d_name);
		lstat(subdir, &statbuf);
		
		if (S_ISDIR(statbuf.st_mode))
		{
			if (strcmp(".", entry->d_name) == 0 ||
                    		strcmp("..", entry->d_name) == 0)
			{
				continue;
			}

			long long int subDirSize = getDirSize(subdir);
			totalSize+=subDirSize;
		}
		else
		{
			totalSize+=statbuf.st_size;
		}
	}

	closedir(dp);	
    return totalSize;
}

unsigned long LogDirCtrl::getDirCount(char *dirPath)
{
    unsigned long DirCount = 0;
    struct stat statbuff;
    DIR *dp;
    struct dirent *dirp;

    if ((dp = opendir(dirPath)) == NULL)
    {
        XAG_LOG_E("can't open %s\n", dirPath);
        mkdir(dirPath,0777);
        return 0;
    }

    while ((dirp = readdir(dp)) != NULL)
    {

         if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
        {
            continue;
        }
        //printf("%s%s/n",root,ptr->d_name);
        //如果是目录，则递归调用 get_file_count函数

        if (dirp->d_type == DT_DIR)//目录下还有目录，直接删除
        {
            DirCount++;
        }
    }

    closedir(dp);
    return DirCount;
}


unsigned long LogDirCtrl::getDirFileCount(char *dirPath)//获取目录下的文件数
{
    DIR *dir;
    struct dirent * ptr;
    int total = 0;
    char path[128];
    char cmd[128];
    dir = opendir(dirPath); /* 打开目录*/
    if (dir == NULL)
    {
        XAG_LOG_E("fail to open dir");
        return 0;
    }

   
    while ((ptr = readdir(dir)) != NULL)
    {
        //顺序读取每一个目录项；
        //跳过“..”和“.”两个目录
        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
        {
            continue;
        }
        //printf("%s%s/n",root,ptr->d_name);
        //如果是目录，则递归调用 get_file_count函数

        if (ptr->d_type == DT_DIR)//目录下还有目录，直接删除
        {
            sprintf(path, "%s%s", dirPath, ptr->d_name);
            printf("getDirFileCount %s\n", path);
            //total += getDirFileCount(path);
            sprintf(cmd, "rm -r %s", path);
            system(cmd);
           
        }

        if (ptr->d_type == DT_REG)
        {
            total++;
            // printf("%s%s/n",dirPath,ptr->d_name);
        }
    }
   
    closedir(dir);
    return total;
}


unsigned long LogDirCtrl::scanfDirFilebyTime(char *dirPath,int type)//获取目录下的文件夹时间
{
    DIR *dir;
    struct dirent * ptr;
    int total = 0;
    char path[128];
    struct stat buf;
    int result;
    ImageDir_INFO stImageDirInfo;
	FlyMapOutDir_INFO stFlyMapOutInfo;
    dir = opendir(dirPath); /* 打开目录*/
    if (dir == NULL)
    {
        XAG_LOG_E("fail to open dir");
 
    }
  //printf("scanfDirFilebyTime %s\n", dirPath);
   
    while ((ptr = readdir(dir)) != NULL)
    {
        //顺序读取每一个目录项；
        //跳过“..”和“.”两个目录
        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
        {
            continue;
        }
        //printf("%s%s/n",root,ptr->d_name);
        //如果是目录，则递归调用 get_file_count函数

        if (ptr->d_type == DT_DIR)//目录下还有目录，直接删除
        {
            sprintf(path, "%s%s", dirPath, ptr->d_name);
            printf("scanfDirFilebyTime %s\n", path);
            //total += getDirFileCount(path);
             result =stat(path, &buf);
           
		     if(type==IMAGEDIR)
		     	{
             memset(&stImageDirInfo,0,sizeof(stImageDirInfo));
             stImageDirInfo.time = buf.st_mtime;
             memcpy(stImageDirInfo.DirName, ptr->d_name, strlen(ptr->d_name));
             m_imagedirtimelist.push_back(stImageDirInfo);
             total++;
		     	}
			 else if(type==FLYMAPOUTDIR)
			 	{
              memset(&stFlyMapOutInfo,0,sizeof(stFlyMapOutInfo));
             stFlyMapOutInfo.time = buf.st_mtime;
             memcpy(stFlyMapOutInfo.DirName, ptr->d_name, strlen(ptr->d_name));
             m_outdirtimelist.push_back(stFlyMapOutInfo);
             total++;

			 	}
        }

        if (ptr->d_type == DT_REG)
        {
            // printf("%s%s/n",dirPath,ptr->d_name);
        }
    }
 
    closedir(dir);
    return total;
  
}

char* LogDirCtrl::GetImageDirNameByTime(long time)//根据time 去m_dirtimelist 找对应的文件名
{
    int i;
    for (i = 0; i < m_imagedirtimelist.size(); i++)
    {
        if (time == m_imagedirtimelist[i].time)
        {
            return m_imagedirtimelist[i].DirName;
        }
    }

    return NULL;
}

char* LogDirCtrl::GetFlymapOutDirNameByTime(long time)//根据time 去m_dirtimelist 找对应的文件名
{
    int i;
    for (i = 0; i < m_outdirtimelist.size(); i++)
    {
        if (time == m_outdirtimelist[i].time)
        {
            return m_outdirtimelist[i].DirName;
        }
    }

    return NULL;
}


char* LogDirCtrl::GetLogNameByTime(long time)//根据time 去m_filetimelist 找对应的文件名
{
    int i;
    for (i = 0; i < m_filetimelist.size(); i++)
    {
        if (time == m_filetimelist[i].time)
        {
            return m_filetimelist[i].FileName;
        }
    }

    return NULL;
}

void LogDirCtrl::_del_char(char a[], char c)
{
    int i, j;
    for (i = 0, j = 0; *(a + i) != '\0'; i++)
    {
        if (*(a + i) == c)
            continue;
        else
        {
            *(a + j) = *(a + i);
            j++;
        }
    }
    *(a + j) = '\0';
}

bool LogDirCtrl::_isTimeStr(const char *s)
{
    const char *pChar;
    bool rv = true;
    int tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, i;
    while (1)
    {
        i = sscanf(s, "%d_%d_%d_%d_%d_%d", &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6);
        if (i != 6)
        {
            rv = false;
            break;
        }
        //printf("###tmp1,tmp2,tmp3,tmp4,tmp5,tmp6=%d,%d,%d,%d,%d,%d######\n",tmp1,tmp2,tmp3,tmp4,tmp5,tmp6);
        if ((tmp1 > 9999) || (tmp1 < 1000) || (tmp2 > 12) || (tmp3 > 31) || (tmp4 > 24) || (tmp5 > 60) || (tmp6 > 60))
        {
            rv = false;
            break;
        }
        for (pChar = s; *pChar != 0; pChar++)
        {
            if ((*pChar != '_') && ((*pChar < '0') || (*pChar > '9')))
            {
                rv = false;
                break;
            }
        }
        break;
    }
    return rv;
}

bool LogDirCtrl::LogComparison(LOGFILE_INFO a, LOGFILE_INFO b)
{
    return a.time < b.time;
}

void LogDirCtrl::_sortLogFileList(vector<LOGFILE_INFO> &vec)
{
    if(vec.empty())
     {
      return;
     }
    sort(vec.begin(), vec.end(), LogComparison);
    for (vector<LOGFILE_INFO>::iterator it = vec.begin(); it < vec.end(); it++)
    {
        //cout << it->time << " ";
    }
}

bool LogDirCtrl::ImageComparison(ImageDir_INFO a, ImageDir_INFO b)
{
    return a.time < b.time;
}


void LogDirCtrl::_sortImageDirList(vector<ImageDir_INFO> &vec)
{
    if(vec.empty())
     {
      return;
     }
    sort(vec.begin(), vec.end(), ImageComparison);
    for (vector<ImageDir_INFO>::iterator it = vec.begin(); it < vec.end(); it++)
    {
        //cout << it->time << " ";
    }
}

bool LogDirCtrl::FlyMapOutComparison(FlyMapOutDir_INFO a, FlyMapOutDir_INFO b)
{
    return a.time < b.time;
}


void LogDirCtrl::_sortFlyMapOutDirList(vector<FlyMapOutDir_INFO> &vec)
{
    if(vec.empty())
     {
        
      return;
     }
    sort(vec.begin(), vec.end(), FlyMapOutComparison);
    for (vector<FlyMapOutDir_INFO>::iterator it = vec.begin(); it < vec.end(); it++)
    {
        //cout << it->time << " ";
    }
}

void LogDirCtrl::AutoDetectImageDir()// /opt/CameraData/Images/
{
	int s32Ri = 0;
    int s32Ret = 0;
    long s32Size = 0;

	s32Size = getDirCount(IMAGE_STORE_DIR); 
     printf("ImageDirr s32Count=%ld\n", s32Size);
    if (s32Size >= 2)
    {   
        printf("cameraimage dir size more than %d,it's[%lu],and delete the beyond\n",DIR_MAX_SIZE, s32Size);
        s32Ret=scanfDirFilebyTime(IMAGE_STORE_DIR,IMAGEDIR);
        if(s32Ret>0) //找dir文件
          {
        _sortImageDirList(m_imagedirtimelist); //排序
        for (s32Ri = 0; s32Ri < (s32Ret<MAX_DIR_COUNTS?s32Ret-1:MAX_DIR_COUNTS); s32Ri++)//删除MAX_DIR_COUNTS个文件夹           
            delDirFileByTime(m_imagedirtimelist[s32Ri].time,IMAGEDIR); 
         }
    }
}

void LogDirCtrl::AutoDetectFlyMapOutDir()// /flymap/flymap_output
{
	int s32Ri = 0;
	int s32Ret = 0;
	long s32Size = 0;

    s32Size = getDirCount(FLYMAP_OUT_DIR); 
    printf("FlyMapOutDir s32Count=%ld\n", s32Size);
    if (s32Size >= 2)
    {   
        printf("flymapout dir size more than %d,it's[%lu],and delete the beyond\n",DIR_MAX_SIZE, s32Size);
        s32Ret=scanfDirFilebyTime(FLYMAP_OUT_DIR,FLYMAPOUTDIR); 
        if(s32Ret>0) //找dir文件
          {
           _sortFlyMapOutDirList(m_outdirtimelist); //排序
        for (s32Ri = 0; s32Ri < (s32Ret<MAX_DIR_COUNTS?s32Ret-1:MAX_DIR_COUNTS); s32Ri++)//删除MAX_DIR_COUNTS个文件夹           
            delDirFileByTime(m_outdirtimelist[s32Ri].time,FLYMAPOUTDIR); 
         }
        
    }
}



